﻿// //  ********************************************************************************
// //  Copyright (C) 2016 Sebastian Kenter. All rights reserved.
// // 
// //  Name    : PhotonServerProject | LoginServer | AccountLogoutRequestHandler.cs
// //  Created : 2016 - 04 - 08 15:03
// //  Modified: 2016 - 04 - 18 09:38
// //  ********************************************************************************

using System;
using ExitGames.Logging;
using NHibernate;
using PhotonServerCommon;
using PhotonServerCommon.Entities.Domain;
using PhotonServerCommon.Enums;
using PhotonServerCommon.Messages;
using PhotonServerCommon.Messages.Helper;
using PhotonServerFramework.Implementation.Database;
using PhotonServerFramework.Implementation.Handler;
using PhotonServerFramework.Implementation.Server;
using PhotonServerFramework.Implementation.Telegram;
using PhotonServerFramework.Interfaces.Server;
using PhotonServerFramework.Interfaces.Telegram;

namespace LoginServer.Handler.Request
{
    public class AccountLogoutRequestHandler : ServerTelegramHandler
    {
        public override ILogger Logger { get; }
        public override Guid HandlerId { get; set; } = Guid.NewGuid();
        public override HandlerTypes HandlerType => HandlerTypes.Request;
        public override byte HandlerCode => (byte) OperationCodes.Account;
        public override int HandlerSubCode => (int) OperationSubCodes.LogoutAccount;

        public AccountLogoutRequestHandler(ILogger logger)
        {
            Logger = logger;
        }

        public override bool HandleTelegram(ITelegram telegram, IServerPeer serverPeer)
        {
            Logger.InfoFormat("Trying to handle telegram of type={0} with code={1}, subcode={2}", telegram.Type,
                (OperationCodes) telegram.TelegramCode, (OperationSubCodes) telegram.TelegramSubCode);

            bool handled = false;

            AccountT account = null;
            ServerPeer peer = serverPeer as ServerPeer;

            AccountLogoutMessage message =
                MessageSerializer.DeserializeMessage<AccountLogoutMessage>(
                    (byte[]) telegram.TelegramParameters[(byte) ParameterCodes.AccountLogoutMessage]);

            if (message != null)
            {
                if (peer != null)
                {
                    using (ISession session = SessionManager.OpenSession())
                    {
                        using (ITransaction transaction = session.BeginTransaction())
                        {
                            try
                            {
                                account =
                                    session.QueryOver<AccountT>()
                                        .Where(a => a.AccountName == message.LoginName)
                                        .SingleOrDefault<AccountT>();
                                transaction.Commit();
                            }
                            catch (Exception ex)
                            {
                                Logger.ErrorFormat("Operation failed with: {0}", ex.Message);
                                transaction.Rollback();
                            }
                        }

                        if (account != null)
                        {
                            if (account.LoggedIn == 1)
                            {
                                Logger.InfoFormat("Found account for login name {0} - logging out now",
                                    account.AccountName);
                                account.LoggedIn = 0;
                                account.DzUpd = DateTime.Now;
                                account.NamUpd = GetType().Name;
                                account.Tsn += 1;

                                using (ITransaction transaction = session.BeginTransaction())
                                {
                                    try
                                    {
                                        session.Save(account);
                                        transaction.Commit();
                                    }
                                    catch (Exception ex)
                                    {
                                        Logger.ErrorFormat("Operation failed with: {0}", ex.Message);
                                        transaction.Rollback();
                                    }
                                }
                                session.Close();
                                handled = true;
                                peer.SendTelegram(new ResponseTelegram
                                                  {
                                                      TelegramCode = telegram.TelegramCode,
                                                      TelegramSubCode = telegram.TelegramSubCode,
                                                      TelegramParameters = telegram.TelegramParameters,
                                                      ReturnCode = (short) ErrorCodes.AccountLoggedOut,
                                                      DebugMessage =
                                                          EnumHelper.GetEnumDescription(
                                                              ErrorCodes.AccountLoggedOut)
                                                  });
                            }
                            else
                            {
                                Logger.ErrorFormat("Account with login name {0} not logged in", account.AccountName);
                                peer.SendTelegram(new ResponseTelegram
                                                  {
                                                      TelegramCode = telegram.TelegramCode,
                                                      TelegramSubCode = telegram.TelegramSubCode,
                                                      TelegramParameters = telegram.TelegramParameters,
                                                      ReturnCode = (short) ErrorCodes.AccountNotLoggedIn,
                                                      DebugMessage =
                                                          EnumHelper.GetEnumDescription(
                                                              ErrorCodes.AccountNotLoggedIn)
                                                  });
                            }
                        }
                        else
                        {
                            Logger.ErrorFormat("Account for login name {0} not found",
                                telegram.TelegramParameters[(byte) ParameterCodes.LoginName]);
                            peer.SendTelegram(new ResponseTelegram
                                              {
                                                  TelegramCode = telegram.TelegramCode,
                                                  TelegramSubCode = telegram.TelegramSubCode,
                                                  TelegramParameters = telegram.TelegramParameters,
                                                  ReturnCode = (short) ErrorCodes.AccountNotFound,
                                                  DebugMessage =
                                                      EnumHelper.GetEnumDescription(
                                                          ErrorCodes.AccountNotFound)
                                              });
                        }
                    }
                }
                else
                {
                    Logger.ErrorFormat("Server peer invalid - cannot process telegram!");
                }
            }
            else
            {
                Logger.ErrorFormat("Message invalid - cannot process telegram!");
            }
            return handled;
        }
    }
}
